package com.ljf.game;

import com.ljf.game.event.EventManager;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 说明：
 *
 * @Auther: lijinfeng
 * @Date: 2023/11/9
 */
public class WebsocketManager {

    /**
     * 保存连接 session 的地方
     * <p>
     * Key: username
     */
    private static ConcurrentHashMap<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>();

    /**
     * 获得 session
     *
     * @param key
     * @return
     */
    public static WebSocketSession get(String key) {
        if(!StringUtils.hasText(key))
            return null;
        // 获得 session
        return SESSION_POOL.get(key);
    }

    /**
     * 添加 session
     *
     * @param key
     */
    public static void add(String key, WebSocketSession session) {
        WebSocketSession webSocketSession = SESSION_POOL.get(key);
        if (webSocketSession != null){
            WebsocketManager.sendMessage(webSocketSession,new HashMap<>(),"其他地方进行了登录");
            try {
                webSocketSession.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        // 添加 session
        SESSION_POOL.put(key, session);
    }


    /**
     * 删除 session,会返回删除的 session
     *
     * @param key
     * @return
     */
    public static WebSocketSession remove(String key) {
        // 删除 session
        return SESSION_POOL.remove(key);
    }

    /**
     * 根据WebSocketSession获取用户名
     * 假设用户名存储在session的attributes中，键为"username"
     */
    public static String getUsername(WebSocketSession session) {
        if (session == null || session.getAttributes() == null) {
            return "未知用户";
        }
        return (String) session.getAttributes().getOrDefault("username", "非法用户");
    }

    /**
     * 删除并同步关闭连接
     *
     * @param key
     */
    public static void removeAndClose(String key) throws IOException {
        WebSocketSession session = remove(key);
        if (session != null) {
            // 关闭连接
            session.close();
        }
    }

    /**
     * 用来存 WebSocketSession 对象集合  方便在给指定组合批量发送消息
     * <p>
     * Key:appCode+regionCode
     * <p>
     * region: 房间号等唯一标识，区分会话组
     */
    private static ConcurrentHashMap<String, ConcurrentHashMap<String, WebSocketSession>> webSocketGroupMap = new ConcurrentHashMap<>();


    /**
     * 获得 session
     *
     * @param key
     * @return
     */
    public static ConcurrentHashMap<String, WebSocketSession> groupGet(String key) {
        // 获得 session
        return webSocketGroupMap.get(key);
    }

    /**
     * 获得 session
     *
     * @return
     */
    public static ConcurrentHashMap<String, ConcurrentHashMap<String, WebSocketSession>> groupGetAll() {
        // 获得 session
        return webSocketGroupMap;
    }

    /**
     * 添加 session
     *
     * @param key
     */
    public static void groupAdd(String key, ConcurrentHashMap<String, WebSocketSession> sessionGroup) {
        ConcurrentHashMap<String, WebSocketSession> group =  webSocketGroupMap.get(key);
        // 添加 session
        group.putAll(sessionGroup);
        webSocketGroupMap.put(key, group);
    }

    /**
     * 添加 session
     *
     */
    public static void groupAddOne(String groupKey, String memberKey, WebSocketSession memberSession) {
        ConcurrentHashMap<String, WebSocketSession> group =  webSocketGroupMap.get(groupKey);
        // 添加 session
        group.put(memberKey,memberSession);
        webSocketGroupMap.put(groupKey, group);
    }

    /**
     * 删除 session,会返回删除的 session
     *
     * @param key
     * @return
     */
    public static ConcurrentHashMap<String, WebSocketSession> groupRemove(String key) {
        // 删除 session
        return webSocketGroupMap.remove(key);
    }

    /**
     * 删除并同步关闭连接
     *
     * @param key
     */
    public static void groupRemoveAndClose(String key) throws IOException {
        Map<String, WebSocketSession> stringWebSocketSessionMap = groupRemove(key);
        stringWebSocketSessionMap.forEach((k, v) -> {
            WebSocketSession session = remove(k);
            if (session != null) {
                // 关闭连接
                try {
                    session.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    }


    public static ConcurrentHashMap<String, WebSocketSession> getAll() {
        return SESSION_POOL;
    }


    /**
     * 获取需要发送的对象列表
     *
     * @param types
     * @param receiver
     * @return
     */
    private static ConcurrentHashMap<String, WebSocketSession> getSessionMap(String types,String receiver) {
        ConcurrentHashMap<String, WebSocketSession> needSendSessionMap = new ConcurrentHashMap<>();
        switch (types) {
            case "ALL":
                needSendSessionMap = getWebsocketSessionAll();
                break;
            case "ONE":
                needSendSessionMap = getWebsocketSessionOne(receiver);
                break;
            case "GROUP":
                needSendSessionMap = getWebsocketSessionGroup(receiver);
                break;
        }
        return needSendSessionMap;
    }

    private static ConcurrentHashMap<String, WebSocketSession> getWebsocketSessionOne(String receiver) {
        ConcurrentHashMap<String, WebSocketSession> stringWebSocketSessionConcurrentHashMap = new ConcurrentHashMap<>();
        WebSocketSession webSocketSession = WebsocketManager.get(receiver);
        if (webSocketSession == null) {
            return stringWebSocketSessionConcurrentHashMap;
        }
        stringWebSocketSessionConcurrentHashMap.put(receiver, webSocketSession);
        return stringWebSocketSessionConcurrentHashMap;
    }

    private static ConcurrentHashMap<String, WebSocketSession> getWebsocketSessionGroup(String receiver) {
        ConcurrentHashMap<String, WebSocketSession> stringWebSocketSessionMap = WebsocketManager.groupGet(receiver);
        return stringWebSocketSessionMap;
    }

    private static ConcurrentHashMap<String, WebSocketSession> getWebsocketSessionAll() {
        return WebsocketManager.getAll();
    }





    /**
     * 根据当前用户socket创建一个 分组 websocket
     *
     * @param groupKey
     * @param webSocket
     * @return
     */
    public static ConcurrentHashMap<String, WebSocketSession> createGroup(String groupKey, WebSocketSession webSocket) {
        ConcurrentHashMap<String, WebSocketSession> map = new ConcurrentHashMap<>();
        map.put(getUsername(webSocket),webSocket);
        webSocketGroupMap.put(groupKey, map);
        return groupGet(groupKey);
    }


    /**
     * 构建并发送统一格式的消息给指定会话
     */
    public static void sendMessage(WebSocketSession session, HashMap<String, Object> hashMap, String msg) {
        String jsonResult = EventManager.buildJsonResult(hashMap, msg);
        try {
            session.sendMessage(new TextMessage(jsonResult));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 构建消息并广播给房间内所有人
     */
    public static void sendMessageToAll(ConcurrentHashMap<String, WebSocketSession> roomMap,
                                  HashMap<String, Object> hashMap, String msg) {
        String jsonResult = EventManager.buildJsonResult(hashMap, msg);
        roomMap.forEach((k, s) -> {
            try {
                if (s.isOpen())
                    s.sendMessage(new TextMessage(jsonResult));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * 移除组中单个成员
     *
     * @param groupKey
     * @param memberKey
     */
    public static void groupRemoveOne(String groupKey, String memberKey) {
        ConcurrentHashMap<String, WebSocketSession> groupMap = groupGet(groupKey);
        groupMap.remove(memberKey);
        webSocketGroupMap.put(groupKey, groupMap);
    }



}